/*
 Copyright (c) 2010, André do Nascimento Campos
                     Universidade Federal do Amazonas
                     Manaus, AM - Brazil
                     dcc.ufam.edu.br

 All rights reserved.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package sinalgo.models;

import sinalgo.configuration.Configuration;
import sinalgo.nodes.Node;
import sinalgo.nodes.messages.Message;

/**
 * The superclass of all the EnergyConsumptionModels. Extend this class to
 * implement your own EnergyConsumptionModel.
 */
public abstract class EnergyConsumptionModel extends Model {
	protected double joulesPerByteRx = 0.0001;
	protected double joulesPerByteTx = 0.0002;
	protected double joulesEnabled = 0.00005;
	protected double joulesStandby = 0.00001;

	protected EnergyConsumptionModel() {
		try {
			if (Configuration.hasParameter("EnergyConsumption/joulesPerByteRx"))
				this.joulesPerByteRx = Configuration
						.getDoubleParameter("EnergyConsumption/joulesPerByteRx");
		} catch (Exception e) {
			// Do nothing. Default values will be used
		}
		try {
			if (Configuration.hasParameter("EnergyConsumption/joulesPerByteTx"))
				this.joulesPerByteTx = Configuration
						.getDoubleParameter("EnergyConsumption/joulesPerByteTx");
		} catch (Exception e) {
			// Do nothing. Default values will be used
		}
		try {
			if (Configuration.hasParameter("EnergyConsumption/joulesEnabled"))
				this.joulesEnabled = Configuration
						.getDoubleParameter("EnergyConsumption/joulesEnabled");
		} catch (Exception e) {
			// Do nothing. Default values will be used
		}
		try {
			if (Configuration.hasParameter("EnergyConsumption/joulesStandby"))
				this.joulesStandby = Configuration
						.getDoubleParameter("EnergyConsumption/joulesStandby");
		} catch (Exception e) {
			// Do nothing. Default values will be used
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see models.Model#getType()
	 */
	public final ModelType getType() {
		return ModelType.EnergyConsumptionModel;
	}

	/**
	 * Uses up the energy needed for sending a message
	 * 
	 * @param the
	 *            node that sent the message
	 */
	public abstract void messageSent(Node node, Message message,
			double intensity);

	/**
	 * Uses up the energy needed for receiving a message
	 * 
	 * @param the
	 *            node that sent the message
	 */
	public abstract void messageReceived(Node node, Message message);

	/**
	 * Uses up the energy needed for acknowledging a message
	 * 
	 * @param the
	 *            node that sent the message
	 */
	public abstract void messageAcked(Node node, Message message,
			double intensity);

	/**
	 * Verifies if a node has enough energy to send a message
	 * 
	 * @param the
	 *            node to send the message
	 */
	public abstract boolean hasEnergyToSend(Node node, Message message,
			double intensity);

	/**
	 * Verifies if a node has enough energy to receive a message
	 * 
	 * @param the
	 *            node to receive the message
	 */
	public abstract boolean hasEnergyToReceive(Node node, Message message,
			double intensity);

	/**
	 * Verifies if a node has enough energy to ack a message
	 * 
	 * @param the
	 *            node to ack the message
	 */
	public abstract boolean hasEnergyToAck(Node node, Message message,
			double intensity);

	/**
	 * Uses the energy on each step (the cost of keeping this on)
	 * 
	 * @param the
	 *            node
	 */
	public void step(Node node) {
		switch (node.getState()) {
		case Enabled:
			enabledStep(node);
			break;
		case WakingUp:
			enabledStep(node);
			break;
		case StandBy:
			standByStep(node);
			break;
		default:
			break;
		}
	}

	/**
	 * Uses the energy on to keep the node on
	 * 
	 * @param the
	 *            node
	 */
	public abstract void enabledStep(Node node);

	/**
	 * Uses the energy on to keep the node in stand-by
	 * 
	 * @param the
	 *            node
	 */
	public abstract void standByStep(Node node);

	public double getJoulesPerByteRx() {
		return joulesPerByteRx;
	}

	public void setJoulesPerByteRx(double joulesPerByteRx) {
		this.joulesPerByteRx = joulesPerByteRx;
	}

	public double getJoulesPerByteTx() {
		return joulesPerByteTx;
	}

	public void setJoulesPerByteTx(double joulesPerByteTx) {
		this.joulesPerByteTx = joulesPerByteTx;
	}

	public double getJoulesEnabled() {
		return joulesEnabled;
	}

	public void setJoulesEnabled(double joulesEnabled) {
		this.joulesEnabled = joulesEnabled;
	}

	public double getJoulesStandby() {
		return joulesStandby;
	}

	public void setJoulesStandby(double joulesStandby) {
		this.joulesStandby = joulesStandby;
	}
	
	

}
